package space.yangmin.baidu.downloader.mode;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponentsBuilder;
import space.yangmin.baidu.downloader.bo.AuthorizationInfo;
import space.yangmin.baidu.downloader.config.BaiduNetDiskConfig;

/**
 * @Description 授权码模式
 * @Version 1.0.0
 * @Date 2024/8/7/0007 9:09
 * @Author Administrator
 */
public class AuthorizationCodeMode implements AuthorizationMode{

    private static final String REDIRECT_URI = "oob";
    private static AuthorizationCodeMode instance;

    public static AuthorizationCodeMode getInstance(){
        if (instance == null){
            synchronized (AuthorizationCodeMode.class){
                if (instance == null){
                    instance = new AuthorizationCodeMode();
                }
            }
        }
        return instance;
    }

    private AuthorizationCodeMode(){}

    /**
     * 获取授权url
     * @return
     */
    public String getAuthorizationUrl(){
        BaiduNetDiskConfig baiduNetDiskConfig = SpringUtil.getBean(BaiduNetDiskConfig.class);
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl("http://openapi.baidu.com/oauth/2.0/authorize")
                .queryParam("response_type", "code")
                .queryParam("client_id", baiduNetDiskConfig.getAppKey())
                .queryParam("redirect_uri", REDIRECT_URI)
                .queryParam("scope", "basic,netdisk")
                .queryParam("device_id", baiduNetDiskConfig.getAppId());
        return uriComponentsBuilder.toUriString();
    }

    /**
     * 获取授权AK
     * @param authorizationCode
     * @return
     */
    public AuthorizationInfo getAccessToken(String authorizationCode){
        BaiduNetDiskConfig baiduNetDiskConfig = SpringUtil.getBean(BaiduNetDiskConfig.class);
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl("https://openapi.baidu.com/oauth/2.0/token")
                .queryParam("grant_type", "authorization_code")
                .queryParam("code", authorizationCode)
                .queryParam("client_id", baiduNetDiskConfig.getAppKey())
                .queryParam("client_secret", baiduNetDiskConfig.getSecretKey())
                .queryParam("redirect_uri", REDIRECT_URI);

        HttpResponse httpResponse = HttpRequest.get(uriComponentsBuilder.toUriString())
                .header("User-Agent","pan.baidu.com")
                .execute();
        Assert.isTrue(httpResponse.isOk(),"获取AK接口异常：\n" + httpResponse);
        String body = httpResponse.body();
        Assert.isTrue(JSON.isValid(body),"获取AK接口请求失败：\n" + httpResponse);

        AuthorizationInfo authorizationInfo = JSON.parseObject(body, AuthorizationInfo.class);
        authorizationInfo.setExpireTimestamp(System.currentTimeMillis() + authorizationInfo.getExpiresIn()*1000);
        return authorizationInfo;
    }

    /**
     * 刷新授权AK
     * @param refreshToken
     * @return
     */
    public AuthorizationInfo refreshAccessToken(String refreshToken){
        BaiduNetDiskConfig baiduNetDiskConfig = SpringUtil.getBean(BaiduNetDiskConfig.class);
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl("https://openapi.baidu.com/oauth/2.0/token")
                .queryParam("grant_type", "refresh_token")
                .queryParam("refresh_token", refreshToken)
                .queryParam("client_id", baiduNetDiskConfig.getAppKey())
                .queryParam("client_secret", baiduNetDiskConfig.getSecretKey());

        HttpResponse httpResponse = HttpRequest.get(uriComponentsBuilder.toUriString()).execute();
        Assert.isTrue(httpResponse.isOk(),"刷新AK接口异常");
        String body = httpResponse.body();
        Assert.isTrue(JSON.isValid(body),"刷新AK接口请求失败：\n" + body);

        AuthorizationInfo authorizationInfo = JSON.parseObject(body, AuthorizationInfo.class);
        authorizationInfo.setExpireTimestamp(System.currentTimeMillis() + authorizationInfo.getExpiresIn()*1000);
        return authorizationInfo;
    }

}
